package com.zhentao.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.zhentao.mapper.ChargeUserGiftMapper;
import com.zhentao.model.pojo.user.ChargeUser;
import com.zhentao.model.pojo.user.common.UserInfoCommon;
import com.zhentao.model.pojo.user.gift.ChargeUserGift;
import com.zhentao.model.pojo.user.gift.ChargeUserHistorygift;
import com.zhentao.model.pojo.user.goods.ChargeUserGoods;
import com.zhentao.model.pojo.user.history.ChargePointsHistoryChange;
import com.zhentao.model.pojo.user.history.dto.UserHistoryDto;
import com.zhentao.model.pojo.user.record.ChargeInviteRecord;
import com.zhentao.model.pojo.user.record.ChargeUserIncome;
import com.zhentao.service.*;
import com.zhentao.utils.RedisIdWorker;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Objects;

import static com.zhentao.common.user.UserCommon.CHARGE_POINTS_HISTORY_CHANGE_MINUS;
import static com.zhentao.common.user.UserCommon.CHARGE_USER_LOGIN_KEY_SCHEDULE;
import static com.zhentao.model.pojo.user.common.UserInfoCommon.USER_POINT;

/**
 * @ClassName: ChargeAddBenefitImpl
 * @Author: 振涛教育_Q
 * @Date: 2024/12/18 18:48
 */
@Service
@Slf4j
public class ChargeAddBenefitImpl implements ChargeAddBenefit {
    @Autowired
    private ChargeUserServiceImpl chargeUserService;
    @Autowired
    private ChargeUserIncomeService incomeService;
    @Autowired
    private ChargeInviteRecordService recordService;
    @Autowired
    private KafkaTemplate<String, String> kafkaTemplate;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private RedisIdWorker redisIdWorker;
    @Autowired
    private ChargeUserGiftMapper userGiftMapper;
    @Autowired
    private ChargePointsHistoryChangeService pointsHistoryChangeService;


    /**
     * @param userId
     * @param chargeUser
     * @return void
     * @description 处理用户收益
     * @author 振涛教育_小Q
     * @date 2024/12/18 18:48
     */
    @Override
    @Transactional
    @Async  // 开启异步调用
    public void addBenefit(Long userId, ChargeUser chargeUser) {
        log.info("获得福利用户id：{}", chargeUser.getId());
        // 对获得福利的用户信息进行修改，增加获得的积分和可用余额
        BigDecimal oldBalance = chargeUser.getBalance();
        chargeUser.setBalance(oldBalance.add(UserInfoCommon.USER_BALANCE));
        chargeUser.setPoint(chargeUser.getPoint() + USER_POINT);
        // 对获得福利的用户信息进行一个修改
        chargeUserService.updateById(chargeUser);
        log.info("将获得福利的用户信息，保存在消息队列中------");
        // 消息队列
        // 创建 积分变化类 对象
        UserHistoryDto historyDto = new UserHistoryDto();
        historyDto.setPoints(USER_POINT);
        historyDto.setStatus(0);
        historyDto.setUserId(chargeUser.getId());
        kafkaTemplate.send("charge-user-points", JSON.toJSONString(historyDto));
        log.info("消息保存成功---->>>>>>>");
        log.info("获得福利的用户，已经修改完毕------");
        // 对收益表进行新增,新增获得福利的用户
        ChargeUserIncome income = new ChargeUserIncome();
        income.setUserId(chargeUser.getId());
        income.setTransit(UserInfoCommon.USER_BALANCE);
        ;
        income.setCreateTime(new Date());
        incomeService.save(income);
        // 对邀请人和被邀请人增加
        ChargeInviteRecord inviteRecord = new ChargeInviteRecord();
        inviteRecord.setInvitedTime(new Date());
        inviteRecord.setInviteUserId(chargeUser.getId());
        inviteRecord.setInvitedUserId(userId);
        recordService.save(inviteRecord);
        log.info("异步处理福利获取已经完毕------------");
    }

    /**
     * @param chargeUserGoods
     * @return void
     * @description 处理用户购买商品的积分变化史
     * @author 振涛教育_小Q
     * @date 2025/1/5 0:30
     */
    @Override
    public void purchaseShop(ChargeUserGoods chargeUserGoods) {
        // 判断参数是否有效
        if (StringUtils.isEmpty(chargeUserGoods)) {
            throw new RuntimeException("参数无效 occur params NullPointException");
        }
        // 根据商品id查询对应商品的信息
        ChargeUserGift giftServiceById = userGiftMapper.selectById(chargeUserGoods.getGiftId());

        // 创建积分变化史对象
        ChargePointsHistoryChange pointsHistoryChange = new ChargePointsHistoryChange();
        // 生成唯一id
        long nextId = redisIdWorker.nextId("charge_points_history_change");
        pointsHistoryChange.setId(nextId);
        pointsHistoryChange.setChangeInfo("兑换奖品" + giftServiceById.getName());
        pointsHistoryChange.setPoints(CHARGE_POINTS_HISTORY_CHANGE_MINUS + giftServiceById.getPoint());
        pointsHistoryChange.setUserId(Long.valueOf(chargeUserGoods.getUserId()));
        pointsHistoryChange.setCreateTime(new Date());
        pointsHistoryChangeService.save(pointsHistoryChange);
        log.info("购买商品积分变化完毕-----");
    }


    /**
     * @param
     * @return void
     * @description 在途收益  转换  获得收益
     * @author 振涛教育_小Q
     * @date 2024/12/24 21:18
     */
    @Scheduled(cron = "0 0 0 * * ?")
    public void scheduleTransitToIncome() {
        log.info("定时任务开始执行------scheduleTransitToIncome");
        // 从缓存这种获取用户id
        try {
            Integer userId = Integer.valueOf(Objects.requireNonNull(redisTemplate.opsForValue().get(CHARGE_USER_LOGIN_KEY_SCHEDULE)));
            // 判断收益表中的在途收益是否 > 0 如果大于 0 说明 有在途收益 需要进行转换
            List<ChargeUserIncome> income = incomeService.list(Wrappers.<ChargeUserIncome>lambdaQuery()
                    .eq(ChargeUserIncome::getUserId, userId));
            if (income != null && income.size() > 0) {
                for (ChargeUserIncome userIncome : income) {
                    // 遍历在途收益是否为 0 不等于 0 直接转换
                    if (!userIncome.getTransit().equals(BigDecimal.ZERO)) {
                        userIncome.setIncome(userIncome.getTransit().add(userIncome.getIncome()));
                        log.info("在途收益转换完成-----------------");
                    }
                    // 修改
                    incomeService.updateById(userIncome);
                    // 重置在途收益
                    userIncome.setTransit(BigDecimal.valueOf(0));
                    incomeService.updateById(userIncome);
                }
            }
        } catch (NumberFormatException e) {
            e.printStackTrace();
            log.info("NullPointerException 异常");
            throw new RuntimeException(e);
        }
    }
}
